package com.cheng.config;


import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.cheng.dao.UserMapper;
import com.cheng.pojo.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Repository;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    @Bean public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }

    // 1.创建 realm 对象
    @Bean
    public UserRealm userRealm(){
        return new UserRealm();
    }

    // 2.创建 DefaultWebSecurityManager
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(userRealm);
        return defaultWebSecurityManager;
    }

    // 3.创建 ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager")DefaultWebSecurityManager defaultWebSecurityManager){
        //(1).装载
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        /*
        添加Shiro内置过滤器，常用的有如下过滤器：
        anon： 无需认证就可以访问
        authc： 必须认证才可以访问
        user： 如果使用了记住我功能就可以直接访问
        perms: 拥有某个资源权限才可以访问perms[user:add]
        role： 拥有某个角色权限才可以访问
        filterMap.put("/user/*","authc");  通配符也行
        */
        //(2).访问权限配置
        Map<String,String> filterMap = new LinkedHashMap<String, String>();
        //授权过滤器(特定权限才能进入)
        filterMap.put("/uav/user/manger","perms[admin]"); //大家记得注意顺序！(设置权限要放第一)
        filterMap.put("/uav/user/system","perms[admin]"); //大家记得注意顺序！(设置权限要放第一)
        //只有认证的才能进入
//        filterMap.put("/*","authc");
        filterMap.put("/uav/user/*","authc");
//        filterMap.put("/static/**","anon");
//        filterMap.put("/css/**","anon");
//        filterMap.put("/js/**","anon");
//        filterMap.put("/img/**","anon");
//        filterMap.put("/User/Updata","authc");

        //参数需要一个Map
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        //(3).自定义登录页面和无权限页面
        //登录页面拦截发现没登录会自动跳转的
        shiroFilterFactoryBean.setLoginUrl("/uav/toLogin");     //设置自己的登录页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");

        return shiroFilterFactoryBean;
    }

}

class UserRealm extends AuthorizingRealm{

    //授权 (在进入有权限的url时会进入该方法)
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//        System.out.println("授权");
        //(1).先得到当前用户信息
        Subject subject= SecurityUtils.getSubject();
        User principal = (User) subject.getPrincipal();

//        (2).进行授权
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addStringPermission(principal.getRole());
        return info;
    }
    @Autowired
    UserMapper userMapper;
    //认证  (表单发起登录请求的时候会进入该方法)
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("认证中");
        //(1).数据库的用户名和密码
        if(token==null)return null;
        UsernamePasswordToken userToken = (UsernamePasswordToken)token;
        User user = userMapper.getUserByUsername(userToken.getUsername());
        //(2).判断用户是否合法
        if (user==null) {
            //用户名不存在
            return null; //shiro底层就会抛出 UnknownAccountException
        }
        String username=user.getUsername();
        String password=user.getPassword();

        //(3). 自动验证密码
        // 我们可以使用一个AuthenticationInfo实现类 SimpleAuthenticationInfo
        // shiro会自动帮我们验证！重点是第二个参数就是要验证的正确密码！
        //第一个参数是"当事人" , 将用户信息存入,方便授权的时候使用
        return new SimpleAuthenticationInfo(user, password, "");

    }
}
